# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1069.1.110+1.1069.113.2 -> 1.1069.119.1 # drivers/acpi/pci_root.c 1.4.1.1 -> 1.7 # Makefile 1.190.1.60 -> 1.193.1.36 # drivers/char/serial.c 1.33.1.4 -> 1.44 # arch/i386/kernel/mpparse.c 1.27.1.15 -> 1.30.1.9 # arch/i386/kernel/io_apic.c 1.27.1.6 -> 1.29.1.4 # drivers/acpi/system.c 1.13.1.2 -> 1.16 # arch/i386/kernel/pci-pc.c 1.30.1.4 -> 1.31.1.3 # arch/i386/kernel/setup.c 1.68.1.10 -> 1.70.1.7 # drivers/acpi/bus.c 1.18.1.1 -> 1.20 # include/asm-i386/io_apic.h 1.10.1.3 -> 1.12.1.2 # fs/inode.c 1.36.1.6 -> 1.40.1.3 # diff -Nru a/Makefile b/Makefile --- a/Makefile Thu Nov 20 16:16:44 2003 +++ b/Makefile Thu Nov 20 16:16:44 2003 @@ -93,6 +93,7 @@ CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ -fno-strict-aliasing -fno-common +CFLAGS += -g ifndef CONFIG_FRAME_POINTER CFLAGS += -fomit-frame-pointer endif @@ -306,8 +307,7 @@ $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in xconfig: symlinks - $(MAKE) -C scripts kconfig.tk - wish -f scripts/kconfig.tk + @echo -e "***\n* Sorry, xconfig is broken; use \"make menuconfig\" instead.\n***" menuconfig: include/linux/version.h symlinks $(MAKE) -C scripts/lxdialog all diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c --- a/drivers/acpi/bus.c Thu Nov 20 16:16:44 2003 +++ b/drivers/acpi/bus.c Thu Nov 20 16:16:44 2003 @@ -1407,16 +1407,14 @@ switch (type) { case ACPI_BUS_TYPE_DEVICE: result = acpi_bus_get_status(device); - if (result) - goto end; - break; + if (!result) + break; + if (!device->status.present) + result = -ENOENT; + goto end; default: STRUCT_TO_INT(device->status) = 0x0F; break; - } - if (!device->status.present) { - result = -ENOENT; - goto end; } /* diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c --- a/drivers/acpi/pci_root.c Thu Nov 20 16:16:44 2003 +++ b/drivers/acpi/pci_root.c Thu Nov 20 16:16:44 2003 @@ -61,8 +61,6 @@ acpi_handle handle; struct acpi_pci_id id; struct pci_bus *bus; - u64 mem_tra; - u64 io_tra; }; static LIST_HEAD(acpi_pci_roots); @@ -114,97 +112,6 @@ } } -void -acpi_pci_get_translations ( - struct acpi_pci_id *id, - u64 *mem_tra, - u64 *io_tra) -{ - struct list_head *node = NULL; - struct acpi_pci_root *entry; - - /* TBD: Locking */ - list_for_each(node, &acpi_pci_roots) { - entry = list_entry(node, struct acpi_pci_root, node); - if ((id->segment == entry->id.segment) - && (id->bus == entry->id.bus)) { - *mem_tra = entry->mem_tra; - *io_tra = entry->io_tra; - return; - } - } - - *mem_tra = 0; - *io_tra = 0; -} - - -static u64 -acpi_pci_root_bus_tra ( - struct acpi_resource *resource, - int type) -{ - struct acpi_resource_address16 *address16; - struct acpi_resource_address32 *address32; - struct acpi_resource_address64 *address64; - - while (1) { - switch (resource->id) { - case ACPI_RSTYPE_END_TAG: - return 0; - - case ACPI_RSTYPE_ADDRESS16: - address16 = (struct acpi_resource_address16 *) &resource->data; - if (type == address16->resource_type) { - return address16->address_translation_offset; - } - break; - - case ACPI_RSTYPE_ADDRESS32: - address32 = (struct acpi_resource_address32 *) &resource->data; - if (type == address32->resource_type) { - return address32->address_translation_offset; - } - break; - - case ACPI_RSTYPE_ADDRESS64: - address64 = (struct acpi_resource_address64 *) &resource->data; - if (type == address64->resource_type) { - return address64->address_translation_offset; - } - break; - } - resource = ACPI_PTR_ADD (struct acpi_resource, - resource, resource->length); - } - - return 0; -} - - -static int -acpi_pci_evaluate_crs ( - struct acpi_pci_root *root) -{ - acpi_status status; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - - ACPI_FUNCTION_TRACE("acpi_pci_evaluate_crs"); - - status = acpi_get_current_resources (root->handle, &buffer); - if (ACPI_FAILURE(status)) - return_VALUE(-ENODEV); - - root->io_tra = acpi_pci_root_bus_tra ((struct acpi_resource *) - buffer.pointer, ACPI_IO_RANGE); - root->mem_tra = acpi_pci_root_bus_tra ((struct acpi_resource *) - buffer.pointer, ACPI_MEMORY_RANGE); - - acpi_os_free(buffer.pointer); - return_VALUE(0); -} - - static int acpi_pci_root_add ( struct acpi_device *device) @@ -245,8 +152,6 @@ switch (status) { case AE_OK: root->id.segment = (u16) value; - printk("_SEG exists! Unsupported. Abort.\n"); - BUG(); break; case AE_NOT_FOUND: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -289,10 +194,8 @@ root->id.function = device->pnp.bus_address & 0xFFFF; /* - * Evaluate _CRS to get root bridge resources * TBD: Need PCI interface for enumeration/configuration of roots. */ - acpi_pci_evaluate_crs(root); /* TBD: Locking */ list_add_tail(&root->node, &acpi_pci_roots); @@ -308,7 +211,12 @@ * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ +#ifdef CONFIG_X86 root->bus = pcibios_scan_root(root->id.bus); +#else + root->bus = pcibios_scan_root(root->handle, + root->id.segment, root->id.bus); +#endif if (!root->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Bus %02x:%02x not present in PCI namespace\n", diff -Nru a/drivers/char/serial.c b/drivers/char/serial.c --- a/drivers/char/serial.c Thu Nov 20 16:16:44 2003 +++ b/drivers/char/serial.c Thu Nov 20 16:16:44 2003 @@ -92,9 +92,8 @@ * ever possible. * * CONFIG_SERIAL_ACPI - * Enable support for serial console port and serial - * debug port as defined by the SPCR and DBGP tables in - * ACPI 2.0. + * Enable support for serial ports found in the ACPI + * namespace. */ #include @@ -222,6 +221,10 @@ #ifdef CONFIG_MAGIC_SYSRQ #include #endif +#ifdef ENABLE_SERIAL_ACPI +#include +#include +#endif /* * All of the compatibilty code so we can compile serial.c against @@ -257,6 +260,10 @@ static struct timer_list serial_timer; +#define HP_DIVA_CHECKTIME (1*HZ) +static struct timer_list hp_diva_timer; +static int hp_diva_count = 0; + /* serial subtype definitions */ #ifndef SERIAL_TYPE_NORMAL #define SERIAL_TYPE_NORMAL 1 @@ -793,6 +800,41 @@ } #ifdef CONFIG_SERIAL_SHARE_IRQ +static inline int is_hp_diva_info(struct async_struct *info) +{ + struct pci_dev *dev = info->state->dev; + return (dev && dev->vendor == PCI_VENDOR_ID_HP && + dev->device == PCI_DEVICE_ID_HP_SAS); +} + +static inline int is_hp_diva_irq(int irq) +{ + struct async_struct *info = IRQ_ports[irq]; + return (info && is_hp_diva_info(info)); +} + +/* + * It is possible to "use up" transmit empty interrupts in some + * cases with HP Diva cards. Figure out if there _should_ be a + * transmit interrupt and if so, return a suitable iir value so + * that we can recover when called from rs_timer(). + */ +static inline int hp_diva_iir(int irq, struct async_struct *info) +{ + int iir = serial_in(info, UART_IIR); + + if (is_hp_diva_info(info) && + (iir & UART_IIR_NO_INT) != 0 && + (info->IER & UART_IER_THRI) != 0 && + (info->xmit.head != info->xmit.tail || info->x_char) && + (serial_in(info, UART_LSR) & UART_LSR_THRE) != 0) { + iir &= ~(UART_IIR_ID | UART_IIR_NO_INT); + iir |= UART_IIR_THRI; + } + + return iir; +} + /* * This is the serial driver's generic interrupt routine */ @@ -823,7 +865,7 @@ do { if (!info->tty || - ((iir=serial_in(info, UART_IIR)) & UART_IIR_NO_INT)) { + ((iir=hp_diva_iir(irq, info)) & UART_IIR_NO_INT)) { if (!end_mark) end_mark = info; goto next; @@ -1097,9 +1139,11 @@ #ifdef CONFIG_SERIAL_SHARE_IRQ if (info->next_port) { do { - serial_out(info, UART_IER, 0); - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); + if (!is_hp_diva_info(info)) { + serial_out(info, UART_IER, 0); + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } info = info->next_port; } while (info); #ifdef CONFIG_SERIAL_MULTIPORT @@ -1131,6 +1175,35 @@ } /* + * This subroutine is called when the hp_diva_timer goes off. In + * certain cases (multiple gettys in particular) Diva seems to issue + * only a single transmit empty interrupt instead of one each time + * THRI is enabled, causing interrupts to be "used up". This serves + * to poll the Diva UARTS more frequently than rs_timer() does. + */ +static void hp_diva_check(unsigned long dummy) +{ +#ifdef CONFIG_SERIAL_SHARE_IRQ + static unsigned long last_strobe; + unsigned long flags; + int i; + + if (time_after_eq(jiffies, last_strobe + HP_DIVA_CHECKTIME)) { + for (i = 0; i < NR_IRQS; i++) { + if (is_hp_diva_irq(i)) { + save_flags(flags); cli(); + rs_interrupt(i, NULL, NULL); + restore_flags(flags); + } + } + } + last_strobe = jiffies; + mod_timer(&hp_diva_timer, jiffies + HP_DIVA_CHECKTIME); +#endif +} + + +/* * --------------------------------------------------------------- * Low level utility subroutines for the serial driver: routines to * figure out the appropriate timeout for an interrupt chain, routines @@ -4286,6 +4359,12 @@ break; } + if (hp_diva_count++ == 0) { + init_timer(&hp_diva_timer); + hp_diva_timer.function = hp_diva_check; + mod_timer(&hp_diva_timer, jiffies + HP_DIVA_CHECKTIME); + } + return 0; } @@ -4589,6 +4668,129 @@ } } +#ifdef ENABLE_SERIAL_ACPI +static acpi_status acpi_serial_address(struct serial_struct *req, + struct acpi_resource_address64 *addr) +{ + unsigned long size; + + size = addr->max_address_range - addr->min_address_range + 1; + req->iomem_base = ioremap(addr->min_address_range, size); + if (!req->iomem_base) { + printk("%s: couldn't ioremap 0x%lx-0x%lx\n", __FUNCTION__, + addr->min_address_range, addr->max_address_range); + return AE_ERROR; + } + req->io_type = SERIAL_IO_MEM; + return AE_OK; +} + +static acpi_status acpi_serial_ext_irq(struct serial_struct *req, + struct acpi_resource_ext_irq *ext_irq) +{ + if (ext_irq->number_of_interrupts > 0) { +#ifdef CONFIG_IA64 + req->irq = acpi_register_irq(ext_irq->interrupts[0], + ext_irq->active_high_low, ext_irq->edge_level); +#else + req->irq = ext_irq->interrupts[0]; +#endif + } + return AE_OK; +} + +static acpi_status acpi_serial_port(struct serial_struct *req, + struct acpi_resource_io *io) +{ + req->port = io->min_base_address; + req->io_type = SERIAL_IO_PORT; + return AE_OK; +} + +static acpi_status acpi_serial_irq(struct serial_struct *req, + struct acpi_resource_irq *irq) +{ + if (irq->number_of_interrupts > 0) { +#ifdef CONFIG_IA64 + req->irq = acpi_register_irq(irq->interrupts[0], + irq->active_high_low, irq->edge_level); +#else + req->irq = irq->interrupts[0]; +#endif + } + return AE_OK; +} + +static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data) +{ + struct serial_struct *serial_req = (struct serial_struct *) data; + struct acpi_resource_address64 addr; + acpi_status status; + + status = acpi_resource_to_address64(res, &addr); + if (ACPI_SUCCESS(status)) + return acpi_serial_address(serial_req, &addr); + else if (res->id == ACPI_RSTYPE_EXT_IRQ) + return acpi_serial_ext_irq(serial_req, &res->data.extended_irq); + else if (res->id == ACPI_RSTYPE_IO) + return acpi_serial_port(serial_req, &res->data.io); + else if (res->id == ACPI_RSTYPE_IRQ) + return acpi_serial_irq(serial_req, &res->data.irq); + return AE_OK; +} + +static int acpi_serial_add(struct acpi_device *device) +{ + acpi_status status; + struct serial_struct serial_req; + int line; + + memset(&serial_req, 0, sizeof(serial_req)); + + status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + acpi_serial_resource, &serial_req); + if (ACPI_FAILURE(status)) + return -ENODEV; + + if (!serial_req.iomem_base && !serial_req.port) { + printk("%s: no iomem or port address in %s _CRS\n", __FUNCTION__, + device->pnp.bus_id); + return -ENODEV; + } + + serial_req.baud_base = BASE_BAUD; + serial_req.flags = ASYNC_SKIP_TEST|ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ; + serial_req.xmit_fifo_size = serial_req.custom_divisor = 0; + serial_req.close_delay = serial_req.hub6 = serial_req.closing_wait = 0; + serial_req.iomem_reg_shift = 0; + + line = register_serial(&serial_req); + if (line < 0) + return -ENODEV; + + return 0; +} + +static int acpi_serial_remove(struct acpi_device *device, int type) +{ + return 0; +} + +static struct acpi_driver acpi_serial_driver = { + .name = "serial", + .class = "", + .ids = "PNP0501", + .ops = { + .add = acpi_serial_add, + .remove = acpi_serial_remove, + }, +}; + +static void __devinit probe_serial_acpi(void) +{ + acpi_bus_register_driver(&acpi_serial_driver); +} +#endif /* ENABLE_SERIAL_ACPI */ static struct pci_device_id serial_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, @@ -5550,6 +5752,9 @@ tty_register_devfs(&callout_driver, 0, callout_driver.minor_start + state->line); } +#ifdef ENABLE_SERIAL_ACPI + probe_serial_acpi(); +#endif #ifdef ENABLE_SERIAL_PCI probe_serial_pci(); #endif @@ -5727,6 +5932,8 @@ /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ del_timer_sync(&serial_timer); + if (hp_diva_count > 0) + del_timer_sync(&hp_diva_timer); save_flags(flags); cli(); remove_bh(SERIAL_BH); if ((e1 = tty_unregister_driver(&serial_driver))) diff -Nru a/fs/inode.c b/fs/inode.c --- a/fs/inode.c Thu Nov 20 16:16:44 2003 +++ b/fs/inode.c Thu Nov 20 16:16:44 2003 @@ -56,7 +56,7 @@ */ static LIST_HEAD(inode_in_use); -static LIST_HEAD(inode_unused); +LIST_HEAD(inode_unused); static struct list_head *inode_hashtable; static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */